package com.wnxy.admin.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wnxy.admin.common.handler.Asserts;
import com.wnxy.admin.common.handler.BusinessEnum;
import com.wnxy.admin.dto.AlarmSettingDto;
import com.wnxy.admin.dto.PageResult;
import com.wnxy.admin.entity.AlarmSettings;
import com.wnxy.admin.entity.ChargingPile;
import com.wnxy.admin.entity.ChargingStation;
import com.wnxy.admin.mapper.AlarmSettingsMapper;
import com.wnxy.admin.mapper.ChargingPileMapper;
import com.wnxy.admin.mapper.ChargingStationMapper;
import com.wnxy.admin.service.IAlarmSettingsService;
import com.wnxy.admin.vo.AlarmSettingVo;
import lombok.RequiredArgsConstructor;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author All
 * @since 2023-11-29
 */
@Service
@RequiredArgsConstructor
public class AlarmSettingsServiceImpl extends ServiceImpl<AlarmSettingsMapper, AlarmSettings> implements IAlarmSettingsService {

    private final AlarmSettingsMapper alarmSettingsMapper;
    private final ChargingPileMapper chargingPileMapper;
    private final ChargingStationMapper chargingStationMapper;
    private final ElasticsearchRestTemplate elasticsearchRestTemplate;
    private final RestHighLevelClient client;

    /*
     *  批量/添加报警设置
     * */
    @Override
    @Transactional
    public void addBatchAlarmSetting(List<AlarmSettings> alarmSettingsList) {
        //判断集合是否为空
        if (CollectionUtils.isEmpty(alarmSettingsList)) {
            return;
        }
        //遍历集合添加数据
        alarmSettingsList.forEach(e -> alarmSettingsMapper.insert(e));

        //将数据转换为视图对象并向ES中添加
        List<AlarmSettingVo> alarmSettingVoList = viewChanger(alarmSettingsList);
        elasticsearchRestTemplate.save(alarmSettingVoList);
    }

    /**
     * 删除(绑定充电桩)报警设置
     *
     * @param id 充电桩 ID
     */
    @Override
    @Transactional
    public void removeAlarmSetting(Long id) {
        //判断是否存在该充电桩对象
        ChargingPile chargingPile = chargingPileMapper.selectById(id);
        if (ObjectUtils.isEmpty(chargingPile)) {
            return;
        }

        //查询充电桩对应的报警设置集合
        List<AlarmSettings> alarmSettingsList = alarmSettingsMapper.selectList(Wrappers.lambdaQuery(AlarmSettings.class)
                .eq(AlarmSettings::getChargerId, id));

        //物理删除
        for (AlarmSettings alarmSettings : alarmSettingsList) {
            alarmSettingsMapper.deleteById(alarmSettings);

            //从ES中删除充电桩对应的报警设置
            elasticsearchRestTemplate.delete(String.valueOf(alarmSettings.getAlarmId()), AlarmSettingVo.class);
        }
    }

    @Override
    @Transactional
    public void editAlarmSetting(AlarmSettings alarmSettings) {
        //等级为严重的报警设置不可修改为禁用
        Asserts.fail(alarmSettings.getAlarmLevel() == -1 && alarmSettings.getStatus() == 0,
                BusinessEnum.SETTINGS_CANNOT_BE_DISABLED);

        alarmSettingsMapper.updateById(alarmSettings);

        //更新Es数据库
        UpdateRequest updateRequest = new UpdateRequest("alarmsettingvo", "_doc", String.valueOf(alarmSettings.getAlarmId()));

        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("status", alarmSettings.getStatus());

        updateRequest.doc(updateMap);

        try {
            UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);     // Handle the update response if needed
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("Failed to update Elasticsearch document", e);
        }
    }

    @Override
    public PageResult queryAlarmSetting(AlarmSettingDto alarmSettingDto) {
        // 构建分页参数
        Pageable pageable = PageRequest.of(alarmSettingDto.getPageNum() - 1, alarmSettingDto.getPageSize());

        boolean isContextEmpty = StringUtils.isEmpty(alarmSettingDto.getContext());

        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();

        // 如果上下文不为空，则添加multi-match查询
        if (!isContextEmpty) {
            builder.withQuery(QueryBuilders.multiMatchQuery(alarmSettingDto.getContext(),
                    "alarmName", "stationName", "chargerName"));
        }

        builder.withPageable(pageable);

        SearchHits<AlarmSettingVo> hits = elasticsearchRestTemplate.search(builder.build(), AlarmSettingVo.class);
        List<AlarmSettingVo> alarmSettingVoList = hits.getSearchHits().stream()
                .map(e -> e.getContent())
                .collect(Collectors.toList());

        return new PageResult<>(hits.getTotalHits(), alarmSettingVoList);
    }


    /*
     *  实体类转换视图类
     * */
    public List<AlarmSettingVo> viewChanger(List<AlarmSettings> alarmSettingsList) {
        List<AlarmSettingVo> voList = new ArrayList<>();

        for (AlarmSettings alarm : alarmSettingsList) {
            AlarmSettingVo vo = new AlarmSettingVo();
            vo.setAlarmId(alarm.getAlarmId());
            vo.setAlarmName(alarm.getAlarmName());
            vo.setStationId(alarm.getStationId());
            vo.setChargerId(alarm.getChargerId());

            // 查询充电站和充电桩的信息
            ChargingStation chargingStation = chargingStationMapper.selectById(alarm.getStationId());
            if (chargingStation != null) {
                vo.setStationName(chargingStation.getChargingStationName());
            }
            ChargingPile chargingPile = chargingPileMapper.selectById(alarm.getChargerId());
            if (chargingPile != null) {
                vo.setChargerName(chargingPile.getChargingPileName());
            }

            vo.setAlarmLevel(alarm.getAlarmLevel());
            vo.setStatus(alarm.getStatus());
            vo.setFlag(alarm.getFlag());
            voList.add(vo);
        }
        return voList;
    }
}
